package com.example.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.example.constant.Constant;
import com.example.dao.BusinessUserDao;
import com.example.dao.SysUserDao;
import com.example.dto.PasswordDTO;
import com.example.dto.SysQueryUserDTO;
import com.example.dto.SysUserDTO;
import com.example.entity.BusinessUserEntity;
import com.example.entity.SysUserEntity;
import com.example.exception.BaseException;
import com.example.model.page.PageData;
import com.example.mybatis.service.impl.CrudServiceImpl;
import com.example.security.InfoDetail;
import com.example.security.SecurityUser;
import com.example.security.UserDetail;
import com.example.service.SysMenuService;
import com.example.service.SysUserService;
import com.example.utils.ConvertUtils;
import com.example.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.List;
import java.util.Map;

/**
 * 系统用户服务实现类
 */
@Slf4j
@Service
public class SysUserServiceImpl extends CrudServiceImpl<SysUserDao, SysUserEntity, SysUserDTO> implements SysUserService {

    @Autowired
    private BusinessUserDao businessUserDao;

    @Autowired
    private PasswordEncoder passwordEncoder;
    //    @Autowired
//    private SysPermissionServiceImpl sysPermissionService;
    @Autowired
    private SysMenuService sysMenuService;

    @Override
    public QueryWrapper<SysUserEntity> getWrapper(Map<String, Object> params) {
        QueryWrapper<SysUserEntity> wrapper = new QueryWrapper<>();
        String username = (String) params.get("username");
        wrapper.eq(StringUtils.isNotBlank(username), "t1.username", username);


        // 只显示满足条件的角色，超级租户：所有， 总店：该租户下的所有角色，普通：该门店的角色
        Object tenantId = params.get("tenantId");
        Object storeId = params.get("storeId");
        Object userId = params.get("userId");
        if (tenantId != null) {
            wrapper.eq("s2.tenant_id", tenantId);
        }
        if (storeId != null) {
            wrapper.eq("s1.store_id", storeId);
        }
        if (userId != null) {
            wrapper.eq("t1.id", userId);
        }





        return wrapper;
    }

    @Override
    public List<Long> getUserIdListByDeptId(List<Long> deptIdList) {
        InfoDetail user = SecurityUser.getUser();
        return baseDao.getUserIdListByDeptId(deptIdList, user);
    }

    @Override
    public int getCountByDeptId(Long deptId) {
        InfoDetail infoDetail = SecurityUser.getUser();
        return baseDao.getCountByDeptId(deptId, infoDetail);
    }

    @Override
    public SysUserEntity getSysUsername(String username) {
        return baseDao.getUserByUsername(username);
    }

    @Override
    public List<Long> getUserRoleIds(Long id) {
        return baseDao.getUserRoleIds(id);
    }

    @Override
//    @Cacheable(value = "user", key = "'username:' + #username", unless = "#result == null")
    public UserDetail getByUsername(String username) {
        log.info("用户登录认证：{}", username);
        // 1. 查询用户是否存在
//        SysUserEntity sysUser = baseDao.getUserByUsername(username);
        SysUserEntity sysUser = baseDao.getUserByUsernameTenantStore(username);
        if (sysUser == null) {
            log.warn("用户名不存在: {}", username);
            throw new UsernameNotFoundException("用户名或密码错误");
        }

        // 2. 校验用户状态 1:启用， 0：禁用
        if (sysUser.getStatus() != 1) {
            log.warn("用户已被禁用: {}", username);
            throw new BaseException("账号已被禁用", HttpStatus.UNAUTHORIZED);
        }

        // 3. 获取用户权限列表
//        Set<String> permissions = sysMenuService.getLoginUserPermissions(sysUser);
        Set<String> permissions = sysMenuService.findLoginUserPermissions(sysUser);
        InfoDetail infoDetail = ConvertUtils.sourceToTarget(sysUser, InfoDetail.class);
//        Set<String> permissions = sysMenuService.getCurrentUserPermissions(infoDetail);
        if (permissions == null || permissions.isEmpty()) {
            log.warn("用户没有任何权限: {}", username);
            throw new UsernameNotFoundException("用户没有任何权限");
        }

        infoDetail.setIsBusinessUser(0);
        // 4. 创建并返回UserDetails对象
        return new UserDetail(sysUser.getId(), sysUser.getUsername(), sysUser.getPassword(), sysUser.getStatus(), sysUser.getDeptId(), sysUser.getTenantId(), sysUser.getStoreId(), sysUser.getIsHeadStore(), sysUser.getIsSuperTenant(), infoDetail.getIsBusinessUser(), permissions);
    }

    @Override
    public BusinessUserEntity businessUsernameExist(String username) {
        return businessUserDao.getByBusinessUsername(username);
    }

    @Override
    public void createBusinessUser(Map<String, Object> params) {
        BusinessUserEntity businessUserEntity = new BusinessUserEntity();

        String username = (String) params.get("business_username");
        String avatar_url = (String) params.get("avatar_url");
        String email = (String) params.get("email");

        businessUserEntity.setEmail(email);
        businessUserEntity.setUsername(username);
        businessUserEntity.setHeadUrl(avatar_url);

        businessUserDao.insert(businessUserEntity);
    }

    @Override
    public SysUserEntity selectByTenantId(Long tenantId) {
        QueryWrapper<SysUserEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("tenant_id", tenantId);
        queryWrapper.eq("status", 1);
        queryWrapper.eq("super_admin", 1);
        List<SysUserEntity> tenantId1 = baseDao.selectList(queryWrapper);
        return tenantId1.get(0);

    }

    @Override
    public void deleteIds(List<Long> ids) {
        deleteBatchIds(ids);
        // 删除用户角色关联表
        for (Long id : ids) {
            baseDao.deleteRoleUser(id);
        }
    }

    @Override
    public List<SysUserEntity> selectList(QueryWrapper<SysUserEntity> queryWrapper) {
        return baseDao.selectList(queryWrapper);
    }

    @Override
    public UserDetail getByBusinessUsername(String username) {
        log.info("用户登录认证：{}", username);
        // 1. 查询用户是否存在
        BusinessUserEntity businessUsername = businessUserDao.getByBusinessUsername(username);
        if (businessUsername == null) {
            log.warn("用户名不存在: {}", username);
            throw new UsernameNotFoundException("用户名或密码错误");
        }

        // 2. 校验用户状态 1:启用， 0：禁用
        if (businessUsername.getStatus() != 1) {
            log.warn("用户已被禁用: {}", username);
            throw new BaseException("账号已被禁用", HttpStatus.UNAUTHORIZED);
        }

        // 3. 获取用户权限列表
//        List<String> permissions = sysPermissionService.getUserPermissions(sysUser.getId());
        InfoDetail infoDetail = ConvertUtils.sourceToTarget(businessUsername, InfoDetail.class);
//        Set<String> permissions = sysMenuService.getCurrentUserPermissions(infoDetail);
//        if (permissions == null || permissions.isEmpty()) {
//            log.warn("用户没有任何权限: {}", username);
//            throw new UsernameNotFoundException("用户没有任何权限");
//        }

        Set<String> permissions = new LinkedHashSet<>(List.of("business.list"));
        infoDetail.setIsBusinessUser(1);
        // 4. 创建并返回UserDetails对象
        return new UserDetail(businessUsername.getId(), businessUsername.getUsername(), businessUsername.getPassword(), businessUsername.getStatus(), null, businessUsername.getTenantId(), businessUsername.getStoreId(), null, null, infoDetail.getIsBusinessUser(), permissions);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePassword(PasswordDTO passwordDTO) {
        SysUserEntity entity = baseDao.selectById(passwordDTO.getId());
        if (entity == null) {
            throw new RuntimeException("用户不存在");
        }
        if (!passwordEncoder.matches(passwordDTO.getOldPassword(), entity.getPassword())) {
            throw new BaseException("原密码不正确");
        }

        entity.setPassword(passwordEncoder.encode(passwordDTO.getNewPassword()));
        entity.setUpdateDate(new Date());
        baseDao.updateById(entity);
    }

    @Override
    public PageData<SysUserDTO> selectPage(SysQueryUserDTO sysQueryUserDTO) {
        Map<String, Object> params = JsonUtils.convertClassToMap(sysQueryUserDTO);
        InfoDetail user = SecurityUser.getUser();
        Integer isSuperTenant = user.getIsSuperTenant();
        Integer isHeadStore = user.getIsHeadStore();
        params.put("isSuperTenant", isSuperTenant.equals(1));
        if (isSuperTenant.equals(0)) {
            params.put("tenantId", user.getTenantId());
            if (isHeadStore.equals(0)) {
                params.put("storeId", user.getStoreId());
                params.put("userId", user.getId());
            }
        }

        IPage<SysUserEntity> page = baseDao.selectPage(
                getPage(params, Constant.CREATE_DATE, false),
                getWrapper(params)
        );
        return getPageData(page, SysUserDTO.class);
    }

    @Override
//    @Cacheable(value = "user", key = "'id:' + #id")
    public SysUserDTO getId(Long id) {
        return get(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(SysUserDTO dto) {
        SysUserEntity entity = ConvertUtils.sourceToTarget(dto, SysUserEntity.class);

        if (StringUtils.isNotBlank(dto.getOldPassword())) {
            SysUserEntity sysUserEntity = baseDao.selectById(entity.getId());
            String password = sysUserEntity.getPassword();
            if (!passwordEncoder.matches(dto.getOldPassword(), password)) {
                throw new BaseException("请输入正确的原始密码");
            }


            String newPassword = dto.getPassword();
            if (passwordEncoder.matches(newPassword, password)) {
                throw new BaseException("新密码不能与原密码相同");
            }


            String encode = passwordEncoder.encode(newPassword);
            String confirmPassword = dto.getConfirmPassword();
            if (!passwordEncoder.matches(confirmPassword, encode)) {
                throw new BaseException("请输入正确的确认密码");
            }
            entity.setPassword(encode);
        } else {
            // mybatis的更新策略是：null不更新
            entity.setPassword(null);
        }

        //更新用户
        updateById(entity);


        // 删除用户角色关联表
        baseDao.deleteRoleUser(entity.getId());

        Long creator = SecurityUser.getUserId();
        List<Long> roleIdList = dto.getRoleIdList();

        for (Long roleId : roleIdList) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", snowflake.nextId());
            map.put("roleId", roleId);
            map.put("userId", entity.getId());
            map.put("creator", creator);
            map.put("createDate", new Date());
            baseDao.insertRoleUser(map);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(SysUserDTO dto) {
        SysUserEntity sysUserEntity = ConvertUtils.sourceToTarget(dto, SysUserEntity.class);
        String password = sysUserEntity.getPassword();
        String confirmPassword = dto.getConfirmPassword();
        // 密码加密
        String encode = passwordEncoder.encode(password);
        // 确认密码
        if (!passwordEncoder.matches(confirmPassword, encode)) {
            throw new BaseException("确认密码不一致");
        }
        sysUserEntity.setPassword(encode);
        // 分布式唯一id
        long userId = snowflake.nextId();
        if (sysUserEntity.getId() == null) {
            sysUserEntity.setId(userId);
        }

        sysUserEntity.setDelFlag(0);

        baseDao.insert(sysUserEntity);


        Long tenantId = SecurityUser.getTenantId();
        Long storeId = SecurityUser.getStoreId();
        Long creator = SecurityUser.getUserId();
        List<Long> roleIdList = dto.getRoleIdList();

        for (Long roleId : roleIdList) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", snowflake.nextId());
            map.put("roleId", roleId);
            map.put("userId", userId);
            map.put("tenantId", tenantId);
            map.put("storeId", storeId);
            map.put("creator", creator);
            map.put("createDate", new Date());
            baseDao.insertRoleUser(map);
        }
    }

    @Override
    public void saveThirdOauth2(SysUserDTO dto) {
        SysUserEntity sysUserEntity = ConvertUtils.sourceToTarget(dto, SysUserEntity.class);
        // 分布式唯一id
        sysUserEntity.setId(snowflake.nextId());

        baseDao.insert(sysUserEntity);
    }
}